home *** CD-ROM | disk | FTP | other *** search
- /*************************************************************************************
- *
- * PDP-8 Simulation Program- cpu simulator
- *
- * ©1992 Graham Cox. All Rights Reserved.
- *
- * Modification History:
- * 9/3/92 created from scratch.
- *
- *
- *
- *************************************************************************************/
-
- #include "PDPGlobalEqu.p"
-
- #include "PDPRunner.proto.h"
-
- PDPMemHdl GetMemory(WindowPtr theWindow);
- PDPRegHdl GetCPU(WindowPtr theWindow);
- PrefsRecHdl GetPrefs(WindowPtr theWindow);
- ProcessRecHdl GetProcess(WindowPtr theWindow);
- ControlHandle GetMemScrollbar(WindowPtr theWindow);
- char PDPProcHalted(WindowPtr pW);
-
-
- int CycleProcess(WindowPtr targetProcess)
- {
- /* high level call to execute one machine cycle of target process. Window must be of
- correct kind. Process is extracted from window, instruction at PC location is
- fetched and executed, and the PC is incremented. If an error occurred, the code
- is returned. This procedure is called repeatedly to run a PDP-8 program */
-
- PDPMemHdl procMemory;
- PDPRegHdl procCPU;
- int pdpErr;
-
- if (IsSimulator(targetProcess)) {
- procMemory = GetMemory(targetProcess);
- procCPU = GetCPU(targetProcess);
-
- if (procMemory != NIL) {
- if (procCPU != NIL) {
- pdpErr = FetchInstruction(procCPU,procMemory);
- if (! pdpErr) {
- pdpErr = ExecuteInstruction(procCPU,procMemory);
- RefreshSimWindow(targetProcess);
- }
- return(pdpErr);
- }
- else
- return(TargetHasNoProcessor);
- }
- else
- return(TargetHasNoMemory);
- }
- }
-
-
- int FetchInstruction(PDPRegHdl theCPU,PDPMemHdl theMemory)
- {
- /* gets the instruction from the location in simulated memory pointed to by the PC in
- the processor, and places it in the processors Instruction Register (IR) */
-
- PDPWord address;
- PDPMemPtr memLoc;
-
- address = (*theCPU)->PC;
- if (address < 4097 && address >=0) {
- memLoc = *theMemory + address;
- (*theCPU)->IR = (*memLoc & 0x0FFF);
- return(noErr);
- }
- return(CPUAddressingError);
- }
-
-
- int ExecuteInstruction(PDPRegHdl theCPU,PDPMemHdl theMemory)
- {
- /* decodes the current instruction (in IR) and calls procedures to execute each one
- accordingly. The contents of the ACC, PC and EAR are likely to be changed. The IR
- is left unchanged. If an error occurs, the procedure aborts and returns the code */
-
- Byte opCode,addressMode;
- short operand,pdpErr;
- PDPWord Instruction;
- PDPMemPtr memLoc;
-
- Instruction = (*theCPU)->IR;
- opCode = (Instruction & opcodeMask) >> 9;
- operand = Instruction & operandMask;
- addressMode = (Instruction & addressModeMask) >> 7;
-
- /* decode & execute */
-
- if (opCode < pdpACC) {
- /* explicit addressing operations, calculate effective address (EAR) */
-
- if (addressMode & pageBit)
- /* relative address on current page */
-
- (*theCPU)->EAR = ((*theCPU)->PC & topFiveBits) | operand;
- else
- /* page zero address, top five bits are zero */
-
- (*theCPU)->EAR = operand;
-
- if (addressMode & indirectBit) {
- /* indirect addressing- fetch indirect address. This is the address in the
- location pointed to by the EAR. */
-
- memLoc = *theMemory + (*theCPU)->EAR;
- (*theCPU)->EAR = (*memLoc & 0x0FFF);
- }
- /* EAR now contains the destination address, which is the target address of the
- current opcode, so decode opcode and perform required operation */
-
- pdpErr = DecodeExplicit(opCode,theCPU,theMemory);
- }
- else
- /* accumulator operations- implicit addressing. Group Bit is in addressMode Byte */
-
- pdpErr = DecodeImplicit(operand,addressMode & 2,theCPU);
-
- /* increment program counter so we are pointing at the next instruction */
-
- (*theCPU)->PC ++;
-
- (*theCPU)->PC &= 0x0FFF;
- return(pdpErr);
- }
-
-
- int DecodeExplicit(Byte opCode,PDPRegHdl theCPU,PDPMemHdl theMemory)
- {
- /* executes given opcode, which must be between 0 and 6 */
-
- PDPWord effectiveAddr;
- PDPMemPtr targLocation;
- int cpuErr;
-
- if (opCode >= pdpAND && opCode<pdpACC) {
- effectiveAddr = (*theCPU)->EAR;
-
- if (effectiveAddr >=0 && effectiveAddr < 4096) {
- HLock((Handle) theMemory);
- targLocation = *theMemory + effectiveAddr;
- cpuErr = noErr;
- switch(opCode) {
- case pdpAND:
- (*theCPU)->ACC &= (*targLocation & 0x0FFF); /* MEM & ACC -> ACC */
- break;
- case pdpTAD:
- (*theCPU)->ACC += *targLocation; /* ACC + MEM -> ACC */
- (*theCPU)->ACC &= 0x0FFF;
- break;
- case pdpISZ:
- *targLocation +=1; /* MEM -> MEM+1, IF MEM=0 THEN SKIP */
- *targLocation &= 0x0FFF;
- if (*targLocation ==0)
- (*theCPU)->PC +=1;
- cpuErr = MemWriteUpdateRequest;
- break;
- case pdpDCA:
- *targLocation = (*theCPU)->ACC & 0x0FFF; /* ACC -> MEM, 0 -> ACC */
- (*theCPU)->ACC = 0;
- cpuErr = MemWriteUpdateRequest;
- break;
- case pdpJMS:
- *targLocation = (*theCPU)->PC+1 & 0x0FFF; /* PC -> MEM, EAR -> PC */
- (*theCPU)->PC = effectiveAddr;
- cpuErr = MemWriteUpdateRequest;
- break;
- case pdpJMP:
- (*theCPU)->PC = effectiveAddr -1; /* EAR-1 -> PC */
- break;
- case pdpIO:
- *targLocation = (*theCPU)->ACC; /* ACC -> MEM, MEM -> ACC */
- (*theCPU)->ACC = *targLocation;
- cpuErr = MemWriteUpdateRequest;
- break;
- }
- HUnlock((Handle) theMemory);
- return(cpuErr);
- }
- else
- return(CPUAddressingError);
- }
- else
- return(IllegalInstruction);
- }
-
-
- int DecodeImplicit(int operation,Byte Group,PDPRegHdl theCPU)
- {
- /* executes given implicit operations, in order of priority if multiple operations required */
-
- Byte skipSense;
-
- if (Group) {
- /* Group 2 instructions */
- skipSense = operation & pdpRBit;
-
- if (operation & pdpSMA) {
- if (skipSense) {
- if (!(*theCPU)->ACC & 0x0800)
- (*theCPU)->PC ++;
- }
- else {
- if ((*theCPU)->ACC & 0x0800)
- (*theCPU)->PC ++;
- }
- }
- if (operation & pdpSZA) {
- if (skipSense) {
- if (!(*theCPU)->ACC == 0)
- (*theCPU)->PC ++;
- }
- else {
- if ((*theCPU)->ACC == 0)
- (*theCPU)->PC ++;
- }
- }
- if (operation & pdpSNL) {
- if (skipSense) {
- if (!(*theCPU)->CCR & Link)
- (*theCPU)->PC ++;
- }
- else {
- if ((*theCPU)->CCR & Link)
- (*theCPU)->PC ++;
- }
- }
- if (operation & pdpCLA)
- (*theCPU)->ACC = 0;
- if (operation & pdpHLT) {
- (*theCPU)->CCR |= HaltBit;
- (*theCPU)->PC --;
- return(ProcessHalted);
- }
- }
- else {
- /* Group 1 instructions */
-
- if (operation & pdpCLA)
- (*theCPU)->ACC =0; /* 0 -> ACC */
- if (operation & pdpCLL)
- (*theCPU)->CCR &= 0xFE; /* 0 -> L */
- if (operation & pdpCMA)
- (*theCPU)->ACC ^= 0x0FFF; /* -ACC -> ACC */
- if (operation & pdpCML)
- (*theCPU)->CCR ^= 1; /* -L -> L */
- if (operation & pdpIAC) {
- (*theCPU)->ACC +=1; /* ACC+1 -> ACC */
- (*theCPU)->ACC &= 0x0FFF;
- }
- if (operation & pdpRBit) {
- RotateAndLink(theCPU,rotateRight);
- if (operation & pdpCBit)
- RotateAndLink(theCPU,rotateRight);
- }
- if (operation & pdpLBit) {
- RotateAndLink(theCPU,rotateLeft);
- if (operation & pdpCBit)
- RotateAndLink(theCPU,rotateLeft);
- }
-
- }
- return(noErr);
- }
-
-
- RotateAndLink(PDPRegHdl theCPU,Byte direcSense)
- {
- /* rotates cpu accumulator through the link bit one place in the direction specified */
-
- PDPWord tempAcc;
-
- tempAcc = (*theCPU)->ACC;
- if (direcSense) {
- /* going right */
- tempAcc |= ((*theCPU)->CCR & Link) << 12;
- (*theCPU)->CCR &= 0xFE;
- (*theCPU)->CCR |= (tempAcc & 1);
- tempAcc >>= 1;
- }
- else {
- /* going left */
- tempAcc <<= 1;
- tempAcc |= ((*theCPU)->CCR & Link);
- (*theCPU)->CCR &= 0xFE;
- (*theCPU)->CCR |= (tempAcc & 0x1000) >> 12;
- }
- (*theCPU)->ACC = (tempAcc & 0x0FFF);
- }
-
-
- RunPDP(WindowPtr wListHead)
- {
- /* call repeatedly (once per event loop) to execute a PDP-8 program for this window.
- If process halted, does nothing. Executes at a speed according to preferences
- for this process. If error occurs, error reported and halt bit set. If single
- step, does nothing (use Single Step procedure) */
-
- PrefsRecHdl thePrefs;
- PDPRegHdl theCPU;
- long cTicks;
- int pdpErr;
- WindowPtr targetWindow;
-
- targetWindow = wListHead;
- while (targetWindow != NIL) {
- if (IsSimulator(targetWindow)) {
- thePrefs = GetPrefs(targetWindow);
- if (thePrefs != NIL){
- cTicks = TickCount();
- if ((*thePrefs)->cycleTime + (*thePrefs)->CPUSpeed < cTicks) {
- (*thePrefs)->cycleTime = cTicks;
-
- theCPU = GetCPU(targetWindow);
-
- if (theCPU != NIL) {
- if (!((*theCPU)->CCR & HaltBit || (*thePrefs)->CPUSpeed ==-1)) {
- pdpErr = CycleProcess(targetWindow);
-
- if (pdpErr) {
- if (pdpErr == MemWriteUpdateRequest)
- /* redraw the affected location */
- UpdateMemoryLocation(targetWindow);
- else {
- ShowProcessError(pdpErr,GetProcessID(targetWindow));
- StopPDP(targetWindow);
- }
- }
- }
- }
- }
- }
- }
- targetWindow = (*(WindowPeek)targetWindow).nextWindow;
- }
- }
-
-
- StepPDP(WindowPtr targetWindow)
- {
- /* executes a single cycle of target process */
-
- int pdpErr;
- PrefsRecHdl thePrefs;
-
- if (IsSimulator(targetWindow)) {
- pdpErr = CycleProcess(targetWindow);
- /*
- ScrollToPC(targetWindow);
- */
- if (pdpErr) {
- if (pdpErr == MemWriteUpdateRequest)
- /* redraw the affected location */
- UpdateMemoryLocation(targetWindow);
- else {
- ShowProcessError(pdpErr,GetProcessID(targetWindow));
- StopPDP(targetWindow);
- }
- }
- }
- }
-
-
- StopPDP(WindowPtr targetWindow)
- {
- /* halts processor in target window */
-
- PDPRegHdl theCPU;
- GrafPtr savePort;
-
- if (IsSimulator(targetWindow)) {
- theCPU = GetCPU(targetWindow);
- HaltProcessor(theCPU);
- GetPort(&savePort);
- SetPort(targetWindow);
- SetInverseClip(targetWindow);
- DrawStatusBar(targetWindow,theCPU);
- UnClipWindow(targetWindow);
- SetPort(savePort);
- }
- }
-
-
- ResetPDP(WindowPtr targetWindow)
- {
- /* starts processor in target window. Sets PC to start Vector, and clears other regs */
-
- PDPRegHdl theCPU;
- PrefsRecHdl thePrefs;
-
- if (IsSimulator(targetWindow)) {
- thePrefs = GetPrefs(targetWindow);
- theCPU = GetCPU(targetWindow);
- (*theCPU)->PC = (*thePrefs)->DefaultStart & 0x0FFF;
- (*theCPU)->ACC = 0;
- (*theCPU)->IR = 0;
- (*theCPU)->EAR = 0;
- (*theCPU)->CCR &= 0xFE;
- RefreshSimWindow(targetWindow);
- }
- }
-
-
- ResumePDP(WindowPtr targetWindow)
- {
- PDPRegHdl theCPU;
-
- if (IsSimulator(targetWindow)) {
- theCPU = GetCPU(targetWindow);
- StartProcessor(theCPU);
- SetInverseClip(targetWindow);
- DrawStatusBar(targetWindow,theCPU);
- UnClipWindow(targetWindow);
- }
- }
-
- #define ProcErrorAlertID 132
- #define ErrorStringsID 129
-
- ShowProcessError(int errorID,int ProcessID)
- {
- /* displays alert box with error message. */
-
- Str255 message;
- Str32 idNum,pID;
- int aHit,messageID;
-
- messageID = -errorID -176;
- GetIndString(&message,ErrorStringsID,messageID);
- NumToString(errorID,&idNum);
- NumToString(ProcessID,&pID);
- ParamText(&message,&idNum,"\p",&pID);
- aHit = xAlert(ProcErrorAlertID,NIL);
- }
-
-
-
-
-
-